package sceneGraph;

import javax.vecmath.Color3f;
import javax.vecmath.Point3f;
import javax.vecmath.Vector3f;

import com.sun.opengl.util.texture.Texture;
import com.sun.opengl.util.texture.TextureIO;

public abstract class AbstractPlanetObject extends AbstractSceneObject implements ISceneObject, IIntersectable {

	protected Point3f pos;
	protected float radius;
	private ObjectMesh mesh;
	private Texture texture;

	protected Vector3f upDirection;
	protected Vector3f direction;
	protected Vector3f leftDirection;

	public AbstractPlanetObject(Point3f pos, float radius, Color3f kDiffuse, Color3f kSpecular, Color3f kAmbient, float nShineness) {
		super(kDiffuse, kSpecular, kAmbient, nShineness);
		this.pos = new Point3f(pos);
		this.radius = radius;

		upDirection = new Vector3f(0, 1, 0);
		leftDirection = new Vector3f(-1, 0, 0);
		direction = new Vector3f(0, 0, 1);
	}

	public AbstractPlanetObject(Point3f pos, float radius, String textureFilename, Color3f kDiffuse, Color3f kSpecular, Color3f kAmbient, float nShineness) {
		this(pos, radius, kDiffuse, kSpecular, kAmbient, nShineness);

		try {
			texture = TextureIO.newTexture(getClass().getResourceAsStream(textureFilename), true, null);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public AbstractPlanetObject(Point3f pos, float radius, String meshFilename, float meshScale, Color3f kDiffuse, Color3f kSpecular, Color3f kAmbient,
			float nShineness) {
		this(pos, radius, kDiffuse, kSpecular, kAmbient, nShineness);
		this.mesh = new ObjectMesh(meshFilename, meshScale);
	}

	public void setVectors(Point3f newPos, Vector3f upDirection, Vector3f leftDirection) {
		pos = new Point3f(newPos);
		this.upDirection = new Vector3f(upDirection);
		this.upDirection.normalize();

		this.leftDirection = new Vector3f(leftDirection);
		this.leftDirection.normalize();

		// Calculate direction
		direction = new Vector3f();
		direction.cross(leftDirection, upDirection);
		direction.normalize();

		// Recalculate leftDirection (to be orthogonal)
		this.leftDirection.cross(upDirection, direction);
		this.leftDirection.normalize();
	}

	@Override
	public boolean intersects(Point3f playerPos, float playerRadius) {
		return (pos.distance(playerPos) < radius + playerRadius);
	}

	public Point3f getPosition() {
		return pos;
	}

	public void setPosition(Point3f newPos) {
		pos = new Point3f(newPos);
	}

	public float getRadius() {
		return radius;
	}

	public ObjectMesh getMesh() {
		return mesh;
	}

	public Texture getTexture() {
		return texture;
	}

	public Vector3f getUpDirection() {
		return upDirection;
	}

	public Vector3f getDirection() {
		return direction;
	}

	public Vector3f getLeftDirection() {
		return leftDirection;
	}

	@Override
	public void accept(Visitor visitor) {
		visitor.visit(this);

	}
}
